/*
 * @Author: sky 1575951471@qq.com
 * @Date: 2024-06-10 22:15:43
 * @LastEditors: sky 1575951471@qq.com
 * @LastEditTime: 2024-12-03 22:23:02
 * @FilePath: \sky_esp32Media\components\BSP\XL9555\xl9555.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "xl9555.h"


static uint16_t xl9555_failed = 0;

/**
 * @brief       读取XL9555的16位IO值
 * @param       data：读取数据的存储区
 * @retval      ESP_OK：读取成功；其他：读取失败
 */
esp_err_t xl9555_read_Input_Value (uint16_t *data, uint8_t GPIO_Port)
{
    esp_err_t ret = ESP_FAIL;
    uint8_t tmp;
    if((GPIO_Port & XL9555_GPIO_Port0) == 0x1)
    {
        ret = i2c_num0_read_byte(XL9555_ADDR, XL9555_INPUT_PORT0_REG, &tmp);
        *data = tmp;
    }
    if((GPIO_Port & XL9555_GPIO_Port1) == 0x2)
    {
        ret = i2c_num0_read_byte(XL9555_ADDR, XL9555_INPUT_PORT1_REG, &tmp);
        *data |= ((((uint16_t)tmp) << 8)& 0xFF00);
    }
    return ret;
}

/**
 * @brief       设置XL9555的16位IO值
 * @param       data：控制IO的变量
 * @param       GPIO_Port: 要控制IO所属的端口
 * @retval      ESP_OK：读取成功；其他：读取失败
 */
esp_err_t xl9555_write_Output_Value (uint16_t data, uint8_t GPIO_Port)
{
    esp_err_t ret = ESP_FAIL;
    uint8_t tmp[2] = {0};
    if((GPIO_Port & XL9555_GPIO_Port0) == 0x1)
    {
        tmp[0] = XL9555_OUTPUT_PORT0_REG;
        tmp[1] = (uint8_t)(data & 0x00FF);
        ret = i2c_num0_write_byte(XL9555_ADDR, tmp, 2);
    }
    if((GPIO_Port & XL9555_GPIO_Port1) == 0x2)
    {
        tmp[0] = XL9555_OUTPUT_PORT1_REG;
        tmp[1] = (uint8_t)((data & 0xFF00) >> 8);
        ret = i2c_num0_write_byte(XL9555_ADDR, tmp, 2);
    }
    return ret;
}

esp_err_t xl9555_pin_write(uint16_t pin, uint8_t val)
{
    esp_err_t ret = ESP_FAIL;
    uint16_t r_data = 0;
    ret = xl9555_read_Input_Value(&r_data, XL9555_GPIO_Port0 | XL9555_GPIO_Port1);
    if(val)
    {
        r_data |= (uint16_t)(0xFFFF & pin);
    }else{
        r_data &= ~(uint16_t)(0xFFFF & pin);
    }
    printf("%s config pin status %d \n", __func__, r_data);
    ret = xl9555_write_Output_Value(r_data, XL9555_GPIO_Port0 | XL9555_GPIO_Port1);
    return ret;
}
/**
 * @brief       XL9555的IO配置
 * @param       config_value：IO配置输入或者输出
 * @retval      返回设置的数值
 */
uint16_t xl9555_ioconfig(uint16_t config_value)
{
    /* 从机地址 + CMD + data1(P0) + data2(P1) */
    /* P00、P01、P14、P15、P16、P17为输入，其他引脚为输出 -->1111 0000 0000 0011 注意：0为输出，1为输入*/
    uint8_t data[2];
    uint8_t reg6_data[2] = {XL9555_CONFIG_PORT0_REG, 0};
    uint8_t reg7_data[2] = {XL9555_CONFIG_PORT1_REG, 0};
    data[0] = (uint8_t)(0xFF & config_value);
    data[1] = (uint8_t)(0xFF & (config_value >> 8));
    reg6_data[1] = data[0];
    reg7_data[1] = data[1];
    i2c_num0_write_byte(XL9555_ADDR, reg6_data, 2);
    vTaskDelay(100);
    i2c_num0_write_byte(XL9555_ADDR, reg7_data, 2);
    return config_value;
}

/**
 * @brief       初始化XL9555
 * @param       无
 * @retval      无
 */
void xl9555_init(void)
{
    gpio_config_t gpio_init_struct = {0};
    uint16_t reg_data;      
    
    gpio_init_struct.intr_type = GPIO_INTR_DISABLE;
    gpio_init_struct.mode = GPIO_MODE_INPUT;
    gpio_init_struct.pin_bit_mask = (1ull << XL9555_INT_IO);
    gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;
    gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;
    gpio_config(&gpio_init_struct);                                             /* 配置XL_INT引脚 */
    xl9555_read_Input_Value(&reg_data, XL9555_GPIO_Port0 | XL9555_GPIO_Port1);  //读一次所有的GPIO口，清除中断
    // printf("xl9555_init InputReg_data:%d\n",reg_data);
    xl9555_ioconfig(0xF003);                                                    //配置相应引脚的IO模式(输入(0)、输出(1))

}

/**
 * @brief       按键扫描函数
 * @param       mode:0->不连续;1->连续
 * @retval      键值, 定义如下:
 *              KEY0_PRES, 1, KEY0按下
 *              KEY1_PRES, 2, KEY1按下
 *              KEY2_PRES, 3, KEY2按下
 *              KEY3_PRES, 4, KEY3按下
 */

uint8_t Key_Scan(void)
{
    uint8_t reg_data = 0;
    // xl9555_read_reg1(&reg_data);
    if((reg_data & 0x80)!= 0x80)
    {
        printf("key0 pres down %d\n",reg_data);
    }
    // printf("reg: %d\n",reg_data);
    return reg_data;
}


void Beep_test(void)
{
    static uint8_t flag = 0;
    static uint8_t cnt = 0;
    if((flag == 0)&&(cnt < 2))
    {
        xl9555_pin_write(BEEP_IO, 0);
        cnt++;
        flag = 1;
    }else{
        xl9555_pin_write(BEEP_IO, 1);
        flag = 0;
    }
}